#include "engine.h"
#include "assert.h"
#include "file/file.h"
#include <map>
//#include "StackWalker.h"

#if 1

#include "windows.h"

class AssertKey
{
public:
	string m_FileName;
	int m_Line;

	AssertKey(const char* i_FileName, int i_Line);
};

bool operator<(const string& i_Str1, const string& i_Str2)
{
	unsigned size=unsigned(min(i_Str1.size(),i_Str2.size()));

	for (unsigned n=0; n<size; ++n)
	{
		if (i_Str1[n]<i_Str2[n])
			return true;

		if (i_Str1[n]>i_Str2[n])
			return false;
	}

	return false;
}
bool operator<(const AssertKey& i_Ass1, const AssertKey& i_Ass2)
{
	if (i_Ass1.m_FileName<i_Ass2.m_FileName)
		return true;
	if (i_Ass2.m_FileName<i_Ass1.m_FileName)
		return false;
	if (i_Ass1.m_Line<i_Ass2.m_Line)
		return true;

	return false;
}

AssertKey::AssertKey(const char* i_FileName, int i_Line)
{
	m_FileName=i_FileName;
	m_Line=i_Line;
}

typedef map<AssertKey,bool> AssertMap;
AssertMap gIgnoreAsserts;

void assert2(bool i_Condition, const char* i_Msg, const char* i_File, int i_Line)
{
	if (i_Condition)// || gIgnoreAllAsserts)
		return;

	AssertKey assertKey(i_File,i_Line);

	AssertMap::iterator it=gIgnoreAsserts.find(assertKey);

	if (it!=gIgnoreAsserts.end() && it->second)
		return;


#if 0//def _WINDOWS
	class StackWalkerToLog : public StackWalker
	{
	protected:
		virtual void OnOutput(LPCSTR szText)
		{
			log_t::log(szText);
		}
		virtual void OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName){}
		virtual void OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion){}
		virtual void OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr){}
	};

	StackWalkerToLog sw;
	sw.ShowCallstack();

#endif

	{
		file_t f("log.txt","ab");
		char* sz=_str("%s\nFile:%s Line:%d\n",i_Msg,i_File,i_Line);
		f.writestring(sz);
	}


//	log_t::log(_str("%s\nFile:%s Line:%d",i_Msg,i_File,i_Line));
//	int ret=MessageBoxA(0,str,"Assertion failed",MB_ABORTRETRYIGNORE|MB_ICONHAND|MB_SETFOREGROUND|MB_TASKMODAL);
	int ret=MessageBoxA(0,_str("%s\nFile:%s Line:%d",i_Msg,i_File,i_Line),"Assertion failed",MB_ABORTRETRYIGNORE|MB_ICONHAND|MB_SETFOREGROUND|MB_TASKMODAL);

	if (ret==IDABORT)
	{
		_exit(3);
	}
	else if (ret==IDRETRY)
	{
		__asm { int 3 }
		return;
	}
	else if (ret==IDIGNORE)
	{
		if (MessageBoxA(0,"Ignore this assert permanently?","Ignore this assert permanently?",MB_YESNO|MB_ICONHAND|MB_SETFOREGROUND|MB_TASKMODAL)==IDYES)
		{
			gIgnoreAsserts[assertKey]=true;
			return;
		}
	}
}
#endif